<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>


  <script>

    /*
      视图更新     updateView 用函数代替
      数据更新函数  defineReactive  ---》 object.defineProperty
      监听函数      observer

      核心：如何基于当前的原型链 去实现数组的方法重写
    */
    const arrayPro = Array.prototype;
    const myProto = Object.create(arrayPro); //
    // myProto.push = function() {
    //   arrayPro.push.call(this....)
    // }
    ['push', 'slice', 'splice', 'shift', 'pop', 'unshift'].forEach(methods => {
      myProto[methods] = function () {
        arrayPro[methods].call(this, ...arguments)
        updateView()
      }
    })
    console.log('myProto:', myProto);
    function updateView() {
      console.log('我是视图更新 函数')
    }

    function defineReactive(target, key, value) {
      observer(value) // 对象递归查找

      Object.defineProperty(target, key, {
        get() {
          return value
        },
        set(newValue) {
          if (newValue !== value) {
            observer(newValue)
            value = newValue
            updateView()
          }
        }
      })
    }

    function observer(target) {
      // {} [] 基础类型 按值操作
      if (typeof target !== 'object' || target == null) {
        return target;
      }

      // 判断数组
      if (Array.isArray(target)) {
        target.__proto__ = myProto;
      }


      // 操作引用类型 {}
      for (let key in target) {
        defineReactive(target, key, target[key])
      }
    }


    const data = {
      name: '1801B',
      age: '1',
      gender: 0,
      info: {
        address: '上海'
      },
      list: ['上海', '杭州', '南京']
    }

    observer(data)

    // data.name = 'hello world'
    data.age = 123

    // 对象
    data.info.address = '五四公路'
    // 数组
    data.list.push('北京南')

    console.log("打印后：", data)












  </script>

</body>

</html>
